package per.chenxin.tools.foundation;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

public class Util {

    static private Map mapConnetionItem = null;

    static private Set setClasspath = null;

    static private final String STR_LANGUAGES_FILNAME = "languages.ini";

    static private final String STR_LANGUAG_ = "language_";

    static private final String STR_DEFAULT_LANGUAG = "default_language";

    static private final String STR_CONNECTION_FILNAME = "connection.ini";

    static private final String STR_CONNECTION_COUNT = "connection_count";

    static private final String STR_NAME_ = "name_";

    static private final String STR_CLASSNAME_ = "classname_";

    static private final String STR_URI_ = "uri_";

    static private final String STR_USER_ = "user_";

    static private final String STR_PASSWORD_ = "password_";

    static private final String STR_AUTOCOMMIT_ = "autocommit_";

    static private final String STR_CLASSPATH_FILNAME = "classpath.ini";

    static public String getLanguage() {

        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream(STR_LANGUAGES_FILNAME));
            String strDefaultLanguageIndex = properties.getProperty(STR_DEFAULT_LANGUAG);
            if (strDefaultLanguageIndex != null && strDefaultLanguageIndex.trim().length() != 0)
                return properties.getProperty(STR_LANGUAG_ + strDefaultLanguageIndex);

        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        }
        return Locale.getDefault().getLanguage();
    }

    static public Map getConnectionMap(boolean isRenew) {

        if (isRenew || mapConnetionItem == null)
            mapConnetionItem = getConnectionMap();
        return mapConnetionItem;
    }

    static private Map getConnectionMap() {

        Map map = new HashMap();
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream(STR_CONNECTION_FILNAME));
            String strConnectionCount = properties.getProperty(STR_CONNECTION_COUNT);
            if (strConnectionCount != null && strConnectionCount.trim().length() != 0) {
                int intConnectionCount = Integer.parseInt(strConnectionCount);
                for (int i = 0; i < intConnectionCount; i++) {
                    ConnectionItem connectionItem = new ConnectionItem();

                    connectionItem.setName(properties.getProperty(STR_NAME_ + (i + 1)));
                    connectionItem.setClassName(properties.getProperty(STR_CLASSNAME_ + (i + 1)));
                    connectionItem.setURI(properties.getProperty(STR_URI_ + (i + 1)));
                    connectionItem.setUser(properties.getProperty(STR_USER_ + (i + 1)));
                    connectionItem.setPassword(properties.getProperty(STR_PASSWORD_ + (i + 1)));
                    connectionItem.setAutoCommit(Boolean.parseBoolean(properties.getProperty(STR_AUTOCOMMIT_
                        + (i + 1))));
                    map.put(connectionItem.getName(), connectionItem);
                }
                return map;
            }

        } catch (NumberFormatException e) {
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        }
        return map;
    }

    static public void saveConnectionMap() throws FileNotFoundException {

        Properties properties = new Properties();

        properties.put(STR_CONNECTION_COUNT, new Integer(mapConnetionItem.size()).toString());
        Object[] objsKey = mapConnetionItem.keySet().toArray();
        for (int i = 0; i < objsKey.length; i++) {
            ConnectionItem connectionItem = (ConnectionItem) mapConnetionItem.get(objsKey[i]);
            properties.put(STR_NAME_ + (i + 1), connectionItem.getName());
            properties.put(STR_CLASSNAME_ + (i + 1), connectionItem.getClassName());
            properties.put(STR_URI_ + (i + 1), connectionItem.getURI());
            properties.put(STR_USER_ + (i + 1), connectionItem.getUser());
            properties.put(STR_PASSWORD_ + (i + 1), connectionItem.getPassword());
            properties.put(STR_AUTOCOMMIT_ + (i + 1),
                new Boolean(connectionItem.isAutoCommit()).toString());
        }

        properties.save(new FileOutputStream(STR_CONNECTION_FILNAME), null);
    }

    public static boolean isConnectionItemOK(ConnectionItem connectionItem) {

        if (connectionItem.getURI() == null || connectionItem.getURI().trim().length() == 0)
            return false;
        return true;
    }

    public static String getNotNullString(String str) {

        if (str == null)
            return "";
        return str;
    }

    public static void showErrorMessage(Shell shell, String str) {

        MessageBox messageBox = new MessageBox(shell, SWT.OK);
        messageBox.setMessage(str);
        messageBox.open();
    }

    static public Set getClasspathSet(boolean isRenew) {

        if (isRenew || setClasspath == null)
            setClasspath = getClasspathSet();
        return setClasspath;
    }

    static private Set getClasspathSet() {

        Set set = new HashSet();
        try {
            BufferedReader in = new BufferedReader(new FileReader(STR_CLASSPATH_FILNAME));

            while (true) {
                String str = in.readLine();
                if (str == null)
                    break;
                set.add(str);
            }
            in.close();
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        }
        return set;
    }

    static public void saveClasspathSet() throws FileNotFoundException {

        Object[] objs = setClasspath.toArray();
        PrintWriter out = new PrintWriter(new File(STR_CLASSPATH_FILNAME));
        for (int i = 0; i < objs.length; i++)
            out.println((String) objs[i]);
        out.close();

    }

    public static URLClassLoader getURLClassLoader() {

        Set set = getClasspathSet(true);
        Set setURLClassLoader = new HashSet();
        Object[] objs = set.toArray();
        for (int i = 0; i < objs.length; i++) {

            try {
                File file = new File((String) objs[i]);
                setURLClassLoader.add(new File((String) objs[i]).toURI().toURL());
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
        objs = setURLClassLoader.toArray();
        URL[] urls = new URL[objs.length];
        for (int i = 0; i < objs.length; i++)
            urls[i] = (URL) objs[i];

        return new URLClassLoader(urls, URLClassLoader.getSystemClassLoader());
    }

    private static void setItemIntoTable(final Table table, ResultSetData resultSetData,
        TableColumn sortColumn, int sortDirection) {

        //table.removeAll();

        int indexSortColumn;
        for (indexSortColumn = 0; indexSortColumn < table.getColumnCount(); indexSortColumn++) {
            if (table.getColumn(indexSortColumn) == sortColumn)
                break;
        }

        resultSetData.sort(indexSortColumn, sortDirection);

    }

    public static void setResultSetTable(final Table table, final ResultSetData resultSetData)
        throws SQLException {

        Listener[] listenersSetData = table.getListeners(SWT.SetData);
        for(Listener listenerSetData:listenersSetData){
            table.removeListener(SWT.SetData, listenerSetData);

        }

        TableColumn[] tableColumns = table.getColumns();
        for (int i = 0; i < tableColumns.length; i++)
            tableColumns[i].dispose();

        MetaData[] metaDatas = resultSetData.getMetaDatas();

        for (int i = 0; i < metaDatas.length; i++) {
            TableColumn tableColumn = new TableColumn(table, SWT.NONE);
            //tableColumn.setWidth(metaDatas[i].columnDisplaySize);
            tableColumn.setWidth(100);
            tableColumn.setText(metaDatas[i].columnName);
            tableColumn.addSelectionListener(new SelectionAdapter() {

                @Override
                public void widgetSelected(SelectionEvent e) {

                    TableColumn sortColumn = table.getSortColumn();
                    TableColumn currentColumn = (TableColumn) e.widget;
                    int sortDirection = table.getSortDirection();
                    if (sortColumn == currentColumn) {
                        sortDirection = sortDirection == SWT.UP ? SWT.DOWN : SWT.UP;
                    } else {
                        table.setSortColumn(currentColumn);
                        sortDirection = SWT.UP;
                    }
                    table.setSortDirection(sortDirection);

                    resultSetData.sort(table.indexOf(currentColumn), sortDirection);

                    table.clearAll();
                    //setItemIntoTable(table, resultSetData, true);
                    // update data displayed in table

                }
            });

        }

        resultSetData.append(Constants.INT_RESULT_COUNT);

        table.setItemCount(resultSetData.count);
        table.clearAll();

        table.addListener(SWT.SetData, new Listener() {

            @Override
            public void handleEvent(Event event) {

                TableItem item = (TableItem) event.item;
                int index = table.indexOf(item);
                try {
                    while (index >= resultSetData.getData().size()) {
                        if (resultSetData.append(Constants.INT_RESULT_COUNT) == 0)
                            break;
                    }

                    try {
                        Object[] data = resultSetData.getDataItem(index);
                        MetaData[] metaDatas = resultSetData.getMetaDatas();

                        String[] strsData = new String[metaDatas.length];
                        for (int j = 0; j < metaDatas.length; j++) {
                            try {
                                strsData[j] = DBUtil.toString(metaDatas[j], data[j]);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }

                        }
                        item.setText(strsData);
                        if (resultSetData.setUpdate.contains(index)) {
                            item.setBackground(new Color(item.getDisplay(), 255, 255, 0));
                        }
                    } catch (IndexOutOfBoundsException ioobe) {
                        item.dispose();
                        table.setItemCount(resultSetData.getData().size());
                    }

                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        });



        //setItemIntoTable(table, resultSetData, false);

    }
}
